package com.fjwt.gz.mgr.ctrl.sms;

import com.alibaba.fastjson2.JSONObject;
import com.fjwt.gz.core.cache.RedisUtil;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.core.model.DBsecurityConfig;
import com.fjwt.gz.core.model.SmsConfig;
import com.fjwt.gz.core.utils.SpringBeansUtil;
import com.fjwt.gz.interfaces.ISmsService;
import com.fjwt.gz.mgr.ctrl.CommonCtrl;
import com.fjwt.gz.zhyx.sms.SmsUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@Slf4j
@RestController
@RequestMapping("/api/sms")
public class SmsController extends CommonCtrl {
    @Value("${province.code}")
    private String provinceCode;

    /** 发送短信验证码  **/
    @RequestMapping(value = "/smsCode", method = RequestMethod.POST)
    public ApiRes smsCode(){
        // 验证参数 手机号
        String phone = getValStringRequired("phone");
        //短信类型，通过类型放置对应的rediskey中
        Integer flag = getValInteger("flag");
        log.info("pc端发送手机号，请求地址：/api/sms/smsCode，请求参数：phone：{}，flag：{}",phone,flag);
        if(!SmsConfig.checkMobileNumber(phone)) {
            throw new BizException("请输入有效的手机号码！");
        }
        //校验次数
        sendCountCheck(null,phone);//ip不传，则只校验手机号
        ISmsService smsService = SpringBeansUtil.getBean(provinceCode + "SmsService", ISmsService.class);
        //生成验证码
        String verifyCode = genSmsCode();
        //发送验证码
        smsService.sendSmsCode(CS.SYS_ROLE_TYPE.MANAGER, phone,verifyCode,flag);
        return ApiRes.ok();
    }


    /**校验手机号**/

    @RequestMapping(value = "/checkSmsCode", method = RequestMethod.POST)
    public ApiRes checkSmsCode(){
        // 验证参数 手机号
        String phone = getValStringRequired("phone");
        //短信类型，通过类型放置对应的rediskey中
        Integer flag = getValInteger("flag");
        String smsCode = getValString("smsCode");
        if(!SmsConfig.checkMobileNumber(phone)) {
            throw new BizException("请输入有效的手机号码！");
        }
        //校验验证码
        checkSmsCode(phone,smsCode,flag);
    return ApiRes.ok();
    }

    private void checkSmsCode(String phone, String smsCode, Integer flag) {
        JSONObject smsCOde = SmsUtil.getSmsCOde(CS.SYS_ROLE_TYPE.MANAGER, phone, flag);
        String smsCodeRedis = smsCOde.getString("code");
        if (!smsCodeRedis.equals(smsCode)){
            throw new BizException("验证码错误");
        }
    }

    /**校验手机号次数限制**/
    public void sendCountCheck(String ip,String phone) {
        DBsecurityConfig.SmsSendLimit smsSendLimit = sysConfigService.getDbRedisByConfigKey(DBsecurityConfig.SmsSendLimit.class,"smsSendLimit");
        if (smsSendLimit.getSendMax() == 0) {
            throw new BizException("不允许发送");
        }
        if(StringUtils.isNotBlank(ip)){
            checkCnt(ip,true,smsSendLimit);
        }
        if(StringUtils.isNotBlank(phone)){
            checkCnt(phone,false,smsSendLimit);
        }
    }
    public void checkCnt(String ip,boolean isIp, DBsecurityConfig.SmsSendLimit smsSendLimit){
        //每个ip/手机号1分钟发送三次
        if(isIp){
            String smsCacheKey = CS.getCacheKeySmsCode(CS.SYS_ROLE_TYPE.MANAGER, ip);
            long sendCountL = RedisUtil.increment(smsCacheKey, 1);
            if(sendCountL == 1){
                RedisUtil.expire(smsCacheKey, smsSendLimit.getLimitMinute(), TimeUnit.MINUTES); //缓存x分钟
            }
            if(sendCountL > smsSendLimit.getSendMax()){ //超过xx次
                throw new BizException("短信发送次数超限，请"+ smsSendLimit.getLimitMinute() + "分钟后再试");
            }
        }
        //每个ip/手机号每天10次
        String smsDayCacheKey = CS.getCacheKeySmsDayCnt(CS.SYS_ROLE_TYPE.MANAGER, ip);
        long sendCountD = RedisUtil.increment(smsDayCacheKey, 1);
        if(sendCountD == 1){
            RedisUtil.expire(smsDayCacheKey, smsSendLimit.getLimitHours(), TimeUnit.HOURS); //缓存1天
        }
        Long daySendMax = smsSendLimit.getDaySendIpMax();
        if(!isIp){
            daySendMax = smsSendLimit.getDaySendPhoneMax();
        }
        if(sendCountD > daySendMax){ //超过xx次
            throw new BizException("短信发送次数超限，请稍后再试");
        }
    }
}
